import java.awt.*;
import java.awt.event.*;
import java.net.InetAddress;

import javax.swing.*;

/**
 * Graphical user interface to a Tic Tac Toe application.
 * The GUI is incomplete because it has no associated player.
 * It also needs a routine for checking if one of the players
 * have got five marks in a row.
 */
public class TicTacToeGui extends JFrame implements ActionListener {
	/** Textfield showing what mark you use ('X' or 'O') */
	private JTextField id;
	/** TextArea giving feedback to the user */
	private TextArea display;
	/** The panel containing the board */
	private JPanel boardPanel;
	/** The menu bar */
	private JMenuBar menuBar;
	/** The game submenu */
	private JMenu gameMenu;
	/** Game submenu choices */
	private JMenuItem newGameItem, connectItem, quitItem;
	/** Grid instance */
	JPanel gridPanel;
	
	/** Game instance **/
	private Game game;

	public void addText(String text) {
		display.append(text);
	}
	
	/**
	 * Creates a new GUI.
	 */
	public TicTacToeGui(Game game) {
		this.game = game;

		// Create GUI components:
		// The display at the bottom:
		display = new TextArea("", 4, 30, TextArea.SCROLLBARS_VERTICAL_ONLY);
		display.setEditable(false);
		// The name field at the top:
		id = new JTextField();
		id.setEditable(false);
		// The board:
		gridPanel = new JPanel();
		gridPanel.setLayout(new GridLayout(Constants.BOARD_SIZE, Constants.BOARD_SIZE, 0, 0));
		
		
		for(int row = 0; row < Constants.BOARD_SIZE; row++){
			for(int col = 0; col < Constants.BOARD_SIZE; col++) {
				gridPanel.add(game.getSquare(row, col));
			}
		}
		
		boardPanel = new JPanel();
		boardPanel.add(gridPanel);

		// Place the components:
		Container cp = getContentPane();
		cp.setLayout(new BorderLayout());
		cp.add("South", display);
		cp.add("North", id);
		cp.add("Center", boardPanel);

		// Create the menu.
		menuBar = new JMenuBar();
		setJMenuBar(menuBar);
		gameMenu = new JMenu("Game");
		gameMenu.setMnemonic(KeyEvent.VK_G);
		menuBar.add(gameMenu);
		
		newGameItem = new JMenuItem("New game", KeyEvent.VK_N);
		newGameItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0));
		gameMenu.add(newGameItem);
		
		connectItem = new JMenuItem("Connect to another game", KeyEvent.VK_C);
		connectItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F3, 0));
		gameMenu.add(connectItem);
		
		quitItem = new JMenuItem("Quit", KeyEvent.VK_Q);
		quitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, ActionEvent.ALT_MASK));
		gameMenu.add(quitItem);

		// Add listeners
		newGameItem.addActionListener(this);
		connectItem.addActionListener(this);
		quitItem.addActionListener(this);
		// Add an anonymous WindowListener which calls quit() when the window is closing
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				quit();
			}
		});

		// Place and show the window:
		setTitle("Tic Tac Toe");
		setSize(Constants.WIN_WIDTH, Constants.WIN_HEIGHT);
		setLocation(200, 200);
		setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
		setVisible(true);
	}

	/**
	 * Called when a menu item has been selected.
	 * @param e	The ActionEvent that occured.
	 */
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == newGameItem)
			newGame();
		else if(e.getSource() == quitItem){
			quit();
		}
		else if(e.getSource() == connectItem){
			connect();
		}
	}

	/**
	 * Starts a new game, if the user confirms it in a dialog box.
	 */
	public void newGame() {
		// This method must be modified!
		// If a player is connected, tell him to clearBoard. 
		
		if(JOptionPane.showConfirmDialog(this, "Are you sure you want to start a new game?", "Start over?", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
			String name = JOptionPane.showInputDialog(this, "Please enter a nickname:", "Ottar");
			game.clearBoard();
			game.setMyMark('X');
			try {
			addText("Your address is: " + (InetAddress.getLocalHost()).toString() + ":" + String.valueOf(Constants.SERVER_PORT) + "\n");
			} catch(Exception e)
			{}
			
			game.startNewGame(name);

			id.setText(game.getName() + ": You are player " + game.getMyMark());
		}
	}
	
	/** 
	 * Connects to an existing game. The user must provide an inet address and port
	 */
	public void connect() {
		String wholeAddress = "";
		do
		{
			wholeAddress = JOptionPane.showInputDialog(this, "Please provide the address to the other player: (ip:port)", "127.0.0.1:3050");
		} while(wholeAddress != null && !wholeAddress.contains(":"));
		
		String name = JOptionPane.showInputDialog(this, "Please enter a nickname:", "Kongo");
		String addressArr[] = wholeAddress.split(":");
		String address = addressArr[0];
		int port = Integer.valueOf(addressArr[1]);
		
		game.joinOtherGame(address, port);
	}

	/**
	 * Exits the game, if the user confirms it in a dialog box.
	 * Should notify the opponent that we left the game.
	 */
	public void quit() {
		// This method should be modified!
		if(JOptionPane.showConfirmDialog(this, "Are you sure you want to quit?", "Really quit?", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
			System.exit(0);
		}
	}

	/**
	 * Outputs a message to the user.
	 * @param s	The string to display. Adds a newline to the end of the string.
	 */
	public void println(String s) {
		display.append(s + "\n");
	}

	/**
	 * Outputs a message to the user.
	 * @param s	The string to display.
	 */
	public void print(String s) {
		display.append(s);
	}
}
